package org.apli.haiam.admin.jsf.managed;

import com.apli.controladores.AplinfoFactoryBean;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.ServletContext;
import org.apli.haiam.admin.entidades.UsuarioAdmin;
import org.apli.haiam.ejb.entidades.AdmAccion;
import org.apli.haiam.ejb.entidades.AdmRol;
import org.apli.haiam.ejb.entidades.AdmSistema;
import org.apli.haiam.ejb.entidades.AdmUsuario;
import org.apli.haiam.ejb.interfaces.AdministradorPerfilHaiam;
import org.apli.jsf.managed.JsfBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Clase backing Bean que administra la entidad AdmSistema.
 * <p>
 * <H6>Soporte:HAIAM
 * <I>david_s_1086@hotmail.com,david.carranza@haiam.gob.ec</I></H6>
 *
 * @author david Carranza
 * @version 1.0 30/07/2014
 */
@ManagedBean
@ViewScoped
public class JsfPerfil extends JsfBean<AdmSistema> {

    private static final long serialVersionUID = 1L;
    @EJB
    private AdministradorPerfilHaiam adminPerfil;
    final Logger log = LoggerFactory.getLogger(JsfPerfil.class);
    private List<AdmAccion> accionesAsignados;
    private List<AdmAccion> accionesNoAsignados;
    private List<AdmAccion> accionesRol;
    private List<AdmRol> rolesAsignados;
    private List<AdmRol> rolesSistema;
    private List<AdmRol> rolUsuario;
    private List<AdmRol> rolesNoAsignados;
    private AdmSistema sistemaInicial;
    private AdmSistema sistema;
    private AdmRol rol;
    private AdmUsuario usuario;

    /**
     * Constructor por defecto.
     */
    public JsfPerfil() {
        super();
    }

    /**
     * Inicializa los datos miembros.
     */
    @Override
    protected void inicializar() {
        object = new AdmSistema();
        cargarSistema();
        cargarEjb();
    }

    /**
     * Carga en la variable sistemaInicial en sistema que se inicializó en el
     * AppContextListener Si el sistema es ADMIN se administrara la seguridad de
     * los diferentes sistemas. Caso contrario solo del sistema inicializado
     */
    private void cargarSistema() {
        FacesContext context = FacesContext.getCurrentInstance();
        ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
        sistemaInicial = (AdmSistema) servletContext.getAttribute("sistema");
    }

    /**
     * Graba el registro asociado al objeto que se administra en la página.
     *
     * @return null, se mantiene en la página invocada.
     */
    @Override
    public String grabarAction() {
        return null;
    }

    /**
     * Añade Roles por sistema a la lista de objetos Obtiene una lista de
     * objetos de tipo SelectedItem.
     *
     * @return la lista
     */
    @Override
    public List<SelectItem> getSelectedItem() {
        List<SelectItem> items = new ArrayList<>();
        if (rolesSistema != null) {
            if (rolesSistema.size() > 0) {
                for (AdmRol rolSistema : rolesSistema) {
                    items.add(new SelectItem(rolSistema, rolSistema.getNombre()));
                }
            }
        }
        return items;
    }

    /**
     * Añade sistemas o sistema Obtiene una lista de objetos de tipo
     * SelectedItem.
     *
     * @return lista
     */
    public List<SelectItem> getSelectedItemSistema() {
        List<AdmSistema> datos;
        List<SelectItem> items = new ArrayList<>();
        try {
            if (sistemaInicial != null) {
                if (sistemaInicial.getIdSistema() == 1) {
                    datos = admin.listarOrdenada(AdmSistema.class, "nombre", true);
                    for (AdmSistema obj : datos) {
                        items.add(new SelectItem(obj, obj.getClave() + " - " + obj.getNombre()));
                    }
                } else {
                    items.add(new SelectItem(sistemaInicial, sistemaInicial.getClave() + " - " + sistemaInicial.getNombre()));
                }
            }
            if (items.size() < 2) {
                cargarRolesSistema();
            }
            return items;

        } catch (Exception e) {
            log.error("getSelectedItemSistema() {} ", e.getMessage());
        }
        return null;
    }

    /**
     * Lista de Acciones Asignadas Obtiene una lista de objetos de tipo
     * SelectedItem.
     *
     * @return lista
     */
    public List<SelectItem> getSelectedItemAccionesAsignadas() {
        List<AdmAccion> datos = new ArrayList<>();
        List<SelectItem> items = new ArrayList<>();
        try {
            if (accionesAsignados != null) {
                datos = accionesAsignados;
                for (AdmAccion obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre()));
                }
            }
            return items;
        } catch (Exception e) {
            log.error("getSelectedItemAccionesAsignadas() {} ", e.getMessage());
        }
        return null;
    }

    /**
     * Añade Acciones no asignadas a la lista Obtiene una lista de objetos de
     * tipo SelectedItem.
     *
     * @return lista
     */
    public List<SelectItem> getSelectedItemAccionesNoAsignadas() {
        List<AdmAccion> datos;
        List<SelectItem> items = new ArrayList<>();
        try {
            if (accionesNoAsignados != null) {
                datos = accionesNoAsignados;
                for (AdmAccion obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre()));
                }
            }
            return items;
        } catch (Exception e) {
            log.error("getSelectedItem() {} ", e.getMessage());
        }
        return null;
    }

    /**
     * Lista roles por sistema.
     */
    public void cargarRolesSistema() {
        FacesContext context = FacesContext.getCurrentInstance();
        accionesAsignados = new ArrayList<>();
        accionesNoAsignados = new ArrayList<>();
        rolesAsignados = new ArrayList<>();
        rolesNoAsignados = new ArrayList<>();
        try {
            rolesSistema = new ArrayList<>();
            if (sistema != null && sistema != null) {
                rolesSistema = adminObject.listar(AdmRol.class, "admSistema", sistema);
                log.info("roles por sistema" + rolesSistema.size());
            }
            if (rolesSistema.isEmpty()) {
                accionesAsignados = new ArrayList<>();
                accionesNoAsignados = new ArrayList<>();
            }
        } catch (Exception e) {
            log.error("cargarAcciones() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
    }

    /**
     * Lista acciones asignadas por rol y por sistema Lista acciones no
     * asignadas por rol y por sistema
     */
    public void cargarAcciones() {
        FacesContext context = FacesContext.getCurrentInstance();
        accionesAsignados = new ArrayList<>();
        accionesNoAsignados = new ArrayList<>();
        try {
            if (rol != null && sistema != null) {
                accionesAsignados = adminPerfil.getAccionesPorRolPorSistema(rol, sistema, 0);
                accionesNoAsignados = adminPerfil.getAccionesPorRolPorSistema(rol, sistema, 1);
            }
        } catch (Exception e) {
            log.error("cargarAcciones() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
    }

    /**
     * Graba y asigna los roles al usuario.
     *
     * @return null, retorna a la página invocada.
     */
    public String asignarAccionRolAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            rol.setAdmAccionList(accionesAsignados);
            adminPerfil.asignarAccionesRol(rol, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(bundle.getString("msg.actualizar")));
            cargarAcciones();
        } catch (Exception e) {
            log.error("asignarAccionRolAction() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
        return null;
    }

    /**
     * Lista acciones asignadas por rol y por sistema Lista acciones no
     * asignadas por rol y por sistema
     */
    public void cargarRoles() {
        FacesContext context = FacesContext.getCurrentInstance();
        rolesAsignados = new ArrayList<>();
        rolesNoAsignados = new ArrayList<>();
        try {
            if (usuario != null && sistema != null) {
                rolesAsignados = adminPerfil.getRolesPorUsuarioPorSistema(usuario, sistema, 0);
                rolesNoAsignados = adminPerfil.getRolesPorUsuarioPorSistema(usuario, sistema, 1);
            } else {
                context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "Seleccione sistema y usuario", "Seleccione sistema y usuario"));
            }

        } catch (Exception e) {
            log.error("cargarAcciones() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
    }

    /**
     * Lista de Roles Asignadas Obtiene una lista de objetos de tipo
     * SelectedItem.
     *
     * @return lista
     */
    public List<SelectItem> getSelectedItemRolesAsignadas() {
        List<AdmRol> datos;
        List<SelectItem> items = new ArrayList<>();
        try {
            if (rolesAsignados != null) {
                datos = rolesAsignados;
                for (AdmRol obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre()));
                }
                return items;
            }
        } catch (Exception e) {
            log.error("getSelectedItem() {} ", e.getMessage());
        }
        return null;
    }

    /**
     * Añade Roles no asignadas a la lista Obtiene una lista de objetos de tipo
     * SelectedItem.
     *
     * @return lista
     */
    public List<SelectItem> getSelectedItemRolesNoAsignadas() {
        List<AdmRol> datos;
        List<SelectItem> items = new ArrayList<>();
        try {
            if (rolesNoAsignados != null) {
                datos = rolesNoAsignados;
                for (AdmRol obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre()));
                }
                return items;
            }
        } catch (Exception e) {
            log.error("getSelectedItemRolesNoAsignadas() {} ", e.getMessage());
        }
        return null;
    }

    /**
     * Graba y asigna los roles al usuario.
     *
     */
    public void asignarRolUsuarioAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            List<AdmRol> rolesActuales = adminPerfil.getRolesPorUsuario(usuario, 0);
            List<AdmRol> rolesEliminar = new ArrayList<>();
            for (AdmRol obj : rolesActuales) {
                if (obj.getAdmSistema().equals(sistema)) {
                    rolesEliminar.add(obj);
                }
            }
            rolesActuales.removeAll(rolesEliminar);
            rolesAsignados.addAll(rolesActuales);

            usuario.setAdmRolList(rolesAsignados);
            adminPerfil.asignarRolesUsuario(usuario, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
            context.addMessage(findComponent(context.getViewRoot(), "formDatos1").getClientId(), new FacesMessage(bundle.getString("msg.actualizar")));
            cargarRoles();
        } catch (Exception e) {
            log.error("asignarAccionRolAction() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos1").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
    }

    /**
     * Mótodo optener conexión a EJB de Perfiles.
     */
    @Override
    protected void cargarEjb() {
        super.cargarEjb();
        if (adminPerfil == null) {
            String ejbPath = null;
            try {
                ResourceBundle property = getProperties();
                String ORBContext = property.getString("ORBContext");
                String ejbContextPath = property.getString("ejb.context.path.admin");
                ejbPath = ORBContext + ejbContextPath + "/AdministradorPerfilBeanHaiam";
                adminPerfil = (AdministradorPerfilHaiam) AplinfoFactoryBean.lookupBean(ejbPath, false);
            } catch (Exception e) {
                log.error("cargarEjbPerfil() {} - {} ", ejbPath, e.getMessage());
            }
        }
    }

    @Override
    protected ResourceBundle getProperties() {
        return ResourceBundle.getBundle("aplicacion");
    }

    public List<AdmRol> getRolesAsignados() {
        return rolesAsignados;
    }

    public void setRolesAsignados(List<AdmRol> rolesAsignados) {
        this.rolesAsignados = rolesAsignados;
    }

    public List<AdmRol> getRolesNoAsignados() {
        return rolesNoAsignados;
    }

    public void setRolesNoAsignados(List<AdmRol> rolesNoAsignados) {
        this.rolesNoAsignados = rolesNoAsignados;
    }

    public AdmSistema getSistema() {
        return sistema;
    }

    public void setSistema(AdmSistema sistema) {
        this.sistema = sistema;
    }

    public AdmRol getRol() {
        return rol;
    }

    public void setRol(AdmRol rol) {
        this.rol = rol;
    }

    public List<AdmRol> getRolesSistema() {
        return rolesSistema;
    }

    public void setRolesSistema(List<AdmRol> rolesSistema) {
        this.rolesSistema = rolesSistema;
    }

    public List<AdmAccion> getAccionesAsignados() {
        return accionesAsignados;
    }

    public void setAccionesAsignados(List<AdmAccion> accionesAsignados) {
        this.accionesAsignados = accionesAsignados;
    }

    public List<AdmAccion> getAccionesNoAsignados() {
        return accionesNoAsignados;
    }

    public void setAccionesNoAsignados(List<AdmAccion> accionesNoAsignados) {
        this.accionesNoAsignados = accionesNoAsignados;
    }

    public AdmUsuario getUsuario() {
        return usuario;
    }

    public void setUsuario(AdmUsuario usuario) {
        this.usuario = usuario;
    }

    public List<AdmAccion> getAccionesRol() {
        return accionesRol;
    }

    public void setAccionesRol(List<AdmAccion> accionesRol) {
        this.accionesRol = accionesRol;
    }

    public List<AdmRol> getRolUsuario() {
        return rolUsuario;
    }

    public void setRolUsuario(List<AdmRol> rolUsuario) {
        this.rolUsuario = rolUsuario;
    }
}
